Skip to content

Comments

Adding WebSocket Support#968

Open
anultravioletaurora wants to merge 44 commits intojellyfin:masterfrom
anultravioletaurora:master
Open

Adding WebSocket Support#968
anultravioletaurora wants to merge 44 commits intojellyfin:masterfrom
anultravioletaurora:master

Conversation

@anultravioletaurora
Copy link

@anultravioletaurora anultravioletaurora commented Dec 11, 2025

Adds websocket support to the SDK

Facilitates the initialization and lifecycle of a WebSocket, abstracting the nuts and bolts of this connection from the consumer.

Creates a subscription model for socket events similar to the Kotlin SDK (thank you @nielsvanvelzen), and establishes a constant "SUBSCRIPTION_REGISTRY", of which start and stop messages can be supplied to the server (i.e., when requesting Sessions)

Covers #966


This pull request introduces comprehensive WebSocket support to the SDK, enabling real-time communication with Jellyfin servers.

Key changes include:

  • WebSocketService Integration: The main Api class now includes a webSocket field, providing access to a new WebSocketService instance. This service manages the WebSocket connection lifecycle.
  • Real-time Event Subscriptions: Consumers can subscribe to various OutboundWebSocketMessageTypes (e.g., Sessions, ActivityLogEntry, ScheduledTasksInfo) to receive real-time updates from the Jellyfin server.
  • Automatic Connection Management: The WebSocketService handles connection establishment, automatic reconnection with exponential backoff in case of disconnections, and graceful closure.
  • Authentication and URL Updates: The WebSocket connection is automatically re-established with updated credentials or base path when the Api instance's accessToken or basePath is modified via the new Api.update() method. Clearing the accessToken will disconnect the WebSocket.
  • Keep-Alive Mechanism: The service automatically responds to ForceKeepAlive messages from the server by sending KeepAlive messages to maintain the connection.
  • Customizable Subscription Intervals: Periodic WebSocket message subscriptions can be configured with custom initial delays and intervals.
  • Connection Status Monitoring: A mechanism to listen for changes in the WebSocket connection status has been added.
  • URL Utility: A new buildWebSocketUrl utility function is introduced to correctly convert HTTP/HTTPS URLs to their WS/WSS equivalents.
  • New Constants and Types: Dedicated constants and TypeScript types have been added to support the new WebSocket functionality.

Add an optional event parameter to the onClose and onOpen callbacks

Incorporates the api_key as a searchParam in the websocket URL
@thornbill thornbill added the enhancement New feature or request label Dec 11, 2025
anultravioletaurora and others added 4 commits December 21, 2025 07:27
Lots of refactoring based on Niels' feedback, including a subscription model that can be used by consumers

This will manage the websocket connection entirely
@anultravioletaurora anultravioletaurora marked this pull request as ready for review January 4, 2026 14:24
…n the websocket status

Pulls out the reconnect interval to a separate config
@sonarqubecloud
Copy link

sonarqubecloud bot commented Jan 4, 2026

Moving OutboundWebSocketMessageType to types folder (oopsies)

Setting WebSocketService when authentication methods are called

Closing the websocketservice and disposing when a logout occurs

Extracting PERIODIC_LISTENER_INTERVAL to a config const

Setting WebSocket URL PATH as a config const

exporting types from the websocket index

adding WebSocketStatus as a type

adding a close function that can be called when the user logs out
added getters for fields

moved websocket closure to the api instance instead of the SessionApi

fix linting, fix tests
adjust constructor params in the WebSocketService

Extract constants from api.ts to separate constants file
if there is already a websocketservice and the token is updated, close the existing service before creating the new one
instantiate websocketservice on api construction if accessToken is provided
Copy link
Member

@thornbill thornbill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of the new files are missing the license header 🙂

@thornbill
Copy link
Member

Please update the CHANGELOG also. 🙏

@anultravioletaurora
Copy link
Author

Please update the CHANGELOG also. 🙏

Updated!

@anultravioletaurora
Copy link
Author

A lot of the new files are missing the license header 🙂

Fixed 🙂

anultravioletaurora and others added 7 commits January 21, 2026 18:05
establish intervals for websocket start messages

remove configs.ts in leiu of constants

update tests accordingly
…als to be provided in the api constructor

Set webSocket as a readonly, defined field

Update tests to cover new functionality and refactoring

Update documentation, add example code snippets
*/
createApi(basePath: string, accessToken?: string, axiosInstance?: AxiosInstance): Api {
return new Api(basePath, this.clientInfo, this.deviceInfo, accessToken, axiosInstance);
createApi(basePath: string, accessToken?: string, axiosInstance?: AxiosInstance, webSocketSubscriptionIntervals?: WebSocketSubscriptionIntervals): Api {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outside of the scope for this PR, but I think it would make sense to change this function to take a single object instead. That is easier to work with when options change in future releases.

switch to "addEventListener" instead of onevent for websockets

update tests

make websocketservice lazily instantiated
Comment on lines +90 to +92
this.getUri(WEBSOCKET_URL_PATH, {
[AUTHORIZATION_PARAMETER]: this.accessToken
}),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't really work great when there is no access token (yet)

*
* @returns A function which can be invoked to remove the added listeners
*/
subscribe<T extends OutboundWebSocketMessageType>(messageTypes: T[], onMessage: SocketMessageHandler<T>) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if subscribe() is called but there is no access token set?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My plan is that the webSocket field on the api instance will be undefined until there is an access token set, but let me know if that's undesired behavior 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels weird, because you can also set an access token, start websockets, then unset the access token. At that point the websocket service is accessible.

Set WebSocketService to undefined if there is no accessToken present to work with

The update function will optionally update the websocketservice url if the basepath or accesstoken are updated

export type OutboundWebSocketMessageType = OutboundWebSocketMessage['MessageType'];

export class PeriodicListenerInterval {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an implementation, not a type 😉

address when the token is cleared (e.g. on a logout)

Keep the websocketservice around, but prevent reconnecting

move PeriodicEventListener to "models.ts" and export properly
@thornbill
Copy link
Member

@kody start-review

@kody-ai
Copy link

kody-ai bot commented Jan 30, 2026

Kody Review Complete

Great news! 🎉
No issues were found that match your current review configurations.

Keep up the excellent work! 🚀

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Validate Business Logic: Ask Kody to validate your code against business rules by adding a comment with the @kody -v business-logic command.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug
Performance
Security
Cross File

Access your configuration settings here.

@kody-ai
Copy link

kody-ai bot commented Jan 30, 2026

kody code-review Kody Rules critical

The new test file src/websocket/__tests__/websocket-service.test.ts contains a hardcoded access token: 'test-token-123'. To comply with security best practices, this value should be loaded from environment variables (e.g., process.env.TEST_ACCESS_TOKEN) or another secure configuration method instead of being committed directly into the source code, even for testing purposes. Kody Rule violation: Prohibit Hardcoded Secrets in Source

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants